<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>事件委托案例练习(Event delegation case practice)</title>
  <!-- 
  事件代理（Event Delegation）是一种常用的事件处理技术，它利用了事件的冒泡机制来提高性能和简化代码。
  一、基本概念
  - 事件代理：事件代理是指将事件处理程序绑定到父元素上，而不是直接绑定到每个子元素上。当事件发生时，通过事件冒泡机制，事件会从子元素传递到父元素，父元素的事件处理程序可以捕获并处理这些事件。
  - 冒泡机制：当事件触发时，事件会从目标元素开始，逐层向上传播到父元素，直到达到根元素。

  二、事件代理的优点
  1. 性能优化：
    - 当有大量子元素时，直接为每个子元素添加事件监听器会消耗更多的内存和处理资源。通过事件代理，可以只为一个父元素添加一个事件监听器，从而减少内存使用和提高性能。
  2. 动态元素支持：
    - 如果子元素是动态生成的（例如通过 AJAX 加载或用户交互创建），直接为这些元素添加事件监听器会很麻烦。使用事件代理，父元素的事件监听器可以自动处理新添加的子元素，无需再次绑定事件。

  三、事件代理的实现
  1. 绑定事件到父元素：
    - 将事件监听器绑定到父元素，并在事件处理程序中判断事件的目标（event.target）是否是需要处理的子元素。
    const parentElement = document.getElementById('parent');

    // 为父元素添加事件监听器
    parentElement.addEventListener('click', function(event) {
      // 判断事件目标是否是需要处理的子元素
      if (event.target.matches('.child')) {
        console.log('子元素被点击:', event.target.textContent);
      }
    });

  四、使用场景
  - 列表项点击：在一个动态生成的列表中，使用事件代理来处理每个列表项的点击事件。
  - 表单元素：在表单中处理多个输入框的变化或提交事件。

  五、总结
  - 事件代理是一种通过将事件处理程序绑定到父元素来管理子元素事件的技术。
  - 它利用事件冒泡机制，能够提高性能并简化动态元素的事件处理。
  - 事件代理在处理大量子元素或动态生成元素时尤其有效。
   -->
  <style>
    .active {
      color: red;
      font-size: 20px;
    }
  </style>
</head>
<body>

  <h3>1. 重复子元素监听方式</h3>
  <ul class="list">
    <li class="child1"><button>子元素1</button></li>
    <li class="child1"><button>子元素2</button></li>
    <li class="child1"><button>子元素3</button></li>
    <li class="child1"><button>子元素4</button></li>
    <li class="child1"><button>子元素5</button></li>
  </ul>

  <h3>2. 在父元素监听方式</h3>
  <ul class="delegation-list">
    <li class="child2"><button>子元素1</button></li>
    <li class="child2"><button>子元素2</button></li>
    <li class="child2"><button>子元素3</button></li>
    <li class="child2"><button>子元素4</button></li>
    <li class="child2"><button>子元素5</button></li>
  </ul>

  <h3>3. 获取自定义属性</h3>
  <div class="delegation-custom-attribute">
    <button data-id="1">子元素1</button>
    <button data-id="2">子元素2</button>
    <button data-id="3">子元素3</button>
    <button data-id="4">子元素4</button>
    <button>其他</button>
  </div>

  <script>
    // 1. 获取所有子元素
    const child1Elements = document.querySelectorAll('.child1');
    for (const liEl of child1Elements) {
      // 监听子元素点击事件
      liEl.addEventListener('click', function(event) {
        console.log('子元素被点击1:', event.target);
        addActiveClass(event.currentTarget);
      });
    }

    // 2. 在父元素监听方式
    const delegationListEl = document.querySelector('.delegation-list');
    delegationListEl.onclick = function(event) {
      console.log('子元素被点击2:', event.target);
      addActiveClass(event.target.parentNode);
    }

    function addActiveClass(event) {
      if (event.classList.contains('active')) {
        event.classList.remove('active');
      } else {
        event.classList.add('active');
      }
    }

    // 3. 获取自定义属性
    const delegationCustomAttributeEl = document.querySelector('.delegation-custom-attribute');
    delegationCustomAttributeEl.onclick = function(event) {
      const target = event.target;
      if (target.tagName === 'BUTTON') {
        console.log('自定义属性:', target.dataset.id);
      }
    }


  </script>
  
</body>
</html>